//
//  networkingTools.swift
//  我的微博
//
//  Created by shmily on 15/7/29.
//  Copyright © 2015年 Stanford-IOS8-Swift-shmilyAshen. All rights reserved.
//

import UIKit
import AFNetworking
import SDWebImage

///重定义闭包
typealias Result_Error = (result: [String :AnyObject]?,error:NSError?) ->()

/// 错误区间
private let MyBlogErrorDomain = "netWorkingError"

class NetworkingTools: AFHTTPSessionManager {
    
    //MARK: - 单例模式
    static let sharedNetTool : NetworkingTools = {
        let tool = NetworkingTools(baseURL: NSURL(string: "https://api.weibo.com/"))
        tool.responseSerializer.acceptableContentTypes = NSSet(objects: "application/json", "text/json", "text/javascript","text/plain") as Set<NSObject>
        
        return tool
    }()
    
    //MARK:- 外部调用的方法
    /// 发送微博(带图像或者不带)
    /// :param: status   文本内容
    /// :param: image    发送的图像
    /// :param: finished 完成回调
    func sendBlog(status: String,image: UIImage?,finished: Result_Error) {
        //如果解包为 nil, 则返回
        guard var paras = getAccessToken(finished) else{
            return
        }
        paras["status"] = status
        
        if image == nil { //只发文字
            let urlString = "https://api.weibo.com/2/statuses/update.json"
            request(NetworkingTools.RequestType.POST, urlString: urlString, paras: paras, finished: finished)
        } else { //图片和文字
            let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
            uploadPic(urlString, paras: paras, image: image!, finished: finished)
        }
    }
    
    /**
    获取access_token
    :param: code     授权码
    :param: finished 回调
    */
     func loadAccess_token(code:String,finished: Result_Error) {

        let paras = ["client_id":OAuth().client_id,
            "client_secret":OAuth().appSecret,
            "grant_type":"authorization_code",
            "code":code,
            "redirect_uri":OAuth().redirect_uri
        ]
        let urlString = "https://api.weibo.com/oauth2/access_token"
        
        request(RequestType.POST, urlString: urlString, paras: paras, finished: finished)
    }
    
    /**
    加载用户数据,name和 avator_large
    :param: access_token token
    :param: uid          uid
    :param: finished     完成回调
    */
    func loadUserInfo (uid: String ,finished: Result_Error) {
        //如果解包为 nil, 则返回
        guard var para = getAccessToken(finished) else{
            return
        }
        para["uid"] = uid
        let urlString = "2/users/show.json"

        //发送 get 请求,获取用户信息
        request(RequestType.GET, urlString: urlString, paras: para, finished: finished)
    }
    /**
    将用户及其所关注用户的最新"微博数据"转换成->模型
    */
    func loadStatus(since_id:Int,max_id:Int,finished:(result: [BlogContent]?,error: NSError?) ->()) {
        
        //加载微博
        loadHomeTimeLine(since_id,max_id: max_id) { (result, error) -> () in
            if error != nil {
                finished(result: nil, error: error)
            }
            
            //将 result 转换成 模型数组
            if let status = result?["statuses"] as? [[String: AnyObject]] {
                //kvc
                var list = [BlogContent]()
                for dict in status {
                    list.append(BlogContent(dict: dict))
                }
                //预先加载网络图片
                self.cacheWebImage(list,finished:finished)
            } else {
                finished(result: nil, error: nil)
            }
        }
    }
    
    //缓存图片(调度组)
    private func cacheWebImage(list: [BlogContent],finished:(result: [BlogContent]?,error: NSError?) ->()) {
        let group = dispatch_group_create()
        //下载数据长度
        var dataLength = 0
         var number = 0
        for status in list {
            //如果没有图片,进行下一次循环
            guard let urls = status.picUrls else {
                continue
            }
            for url in urls {
                dispatch_group_enter(group)
                SDWebImageManager.sharedManager().downloadImageWithURL(url, options: SDWebImageOptions(rawValue: 0), progress: nil, completed: { (image, _, _, _, _) -> Void in
                
                    if image != nil {
                        dataLength += UIImagePNGRepresentation(image)!.length
                        number += 1
                    } else {
                        print("图片为 nil, 请检查网络是否错误")
                    }
                    dispatch_group_leave(group)
                })
            }
        }
        dispatch_group_notify(group, dispatch_get_main_queue()) { () -> Void in
            print("共缓存:\(dataLength / 1024) KB,共\(number)副图像")
            finished(result: list, error: nil)
        }
    }
    
    //MARK:- 自定义中间方法(不允许外部访问)
    /**
    获取当前登录用户及其所关注用户的最新微博
    */
    private func loadHomeTimeLine(since_id:Int,max_id:Int,finished:Result_Error) {
        //如果为 nil, 执行,和 if let 相反
        guard var paras = getAccessToken(finished) else {
            return
        }
        if since_id > 0 { //下拉刷新
             paras["since_id"] = since_id
        } else if max_id > 0 { //上拉刷新
            paras["max_id"] = max_id
        }
        
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        request(RequestType.GET, urlString: urlString, paras: paras, finished: finished)
    }
    
/// 上传图像
    private func uploadPic(urlString :String,paras:[String: AnyObject],image: UIImage, finished:Result_Error) {
        let data = UIImagePNGRepresentation(image) // 获取数据
        
        //成功的回调
        let successCaalBack: (NSURLSessionDataTask!,AnyObject!) ->Void = { (_, JSON) -> Void in
            //如果有结果,直接回调
            if let result = JSON as? [String :AnyObject] {
                finished(result: result , error: nil)
            } else {
                //否则,返回错误
                print("没有数据")
                let error = NSError(domain: MyBlogErrorDomain, code: -1, userInfo: ["message" :"返回结果为 nil"])
                finished(result: nil, error: error)
            }
        }
        //失败的回调
        let failCallBack: (NSURLSessionDataTask!, NSError!) -> Void = {(_, error) -> Void in
            finished(result: nil, error: error)
        }
        
        POST(urlString, parameters: paras, constructingBodyWithBlock: { (formData) -> Void in
            formData.appendPartWithFileData( data, name: "pic", fileName:"aaa", mimeType:"application/octet-stream")
            }, success: successCaalBack, failure: failCallBack)
        
        
    }
    
    /**
    发送网络 request 请求
    :param: type       请求类型: get post
    :param: urlString  请求地址的 string 表示
    :param: paras      请求参数
    :param: finished   完成后的回调
    */
    private func request(type: RequestType,urlString :String,paras:[String: AnyObject], finished:Result_Error) {
        //成功的回调
        let successCaalBack: (NSURLSessionDataTask!,AnyObject!) ->Void = { (_, JSON) -> Void in
            //如果有结果,直接回调
            if let result = JSON as? [String :AnyObject] {
                finished(result: result , error: nil)
            } else {
                //否则,返回错误
                print("没有数据")
                let error = NSError(domain: MyBlogErrorDomain, code: -1, userInfo: ["message" :"返回结果为 nil"])
                finished(result: nil, error: error)
            }
        }
        //失败的回调
        let failCallBack: (NSURLSessionDataTask!, NSError!) -> Void = {(_, error) -> Void in
            finished(result: nil, error: error)
        }
        
        //开始执行 request
        switch type {
        case RequestType.GET:
            GET(urlString, parameters: paras, success: successCaalBack, failure: failCallBack)
        case RequestType.POST:
            POST(urlString, parameters: paras, success: successCaalBack, failure: failCallBack)
        }
    }
    
    /**
    获取access_token
    :returns:  返回包含 token 的数组
    */
    private func getAccessToken(finished:Result_Error) -> [String: AnyObject]?{
        if UserInfo.getUserInfo()?.access_token == nil {
            finished(result: nil, error: requestError.errorTokenMiss.throwError())
            return nil
        }
        //返回数组
        return ["access_token":UserInfo.getUserInfo()!.access_token!]
    }
    
    /**
    requst 请求类型*/
    private enum RequestType {
        case GET
        case POST
    }
    
    /// 错误列表
    private enum requestError: Int {
        /// 异常:数据错误
        case errorDataError = -1
        /// 异常: token 缺失
        case errorTokenMiss = -2
        
        private var descript: String {
            switch self {
            case .errorDataError: return "数据错误"
            case .errorTokenMiss: return "token 缺失"
            }
        }
        /**
        抛出对应异常
        */
        private func throwError() -> NSError {
            return NSError(domain: MyBlogErrorDomain, code: rawValue, userInfo: [MyBlogErrorDomain: descript])
        }
    }
    
}
